﻿namespace DimensionsHelper.Client.WinUi.ViewModels;

public partial class FileViewModel : ObservableObject
{
    [ObservableProperty]
    public partial string FileName
    {
        get;
        set;
    } = "";


    public Func<string, bool>? ExistPredicate
    {
        get;
        init;
    }


    public Action<FileViewModel>? RemoveCallback
    {
        get;
        init;
    }


    public string Filter { get; init; } = FileFilters.Text;


    public bool AllowRepetitive
    {
        get;
        set;
    }


    protected virtual bool MultipleSelect => false;


    protected virtual void UpdateMultipleFileOverride(string[] fileNames)
    {
    }


    private bool IsFileValid([NotNullWhen(true)] string? file)
    {
        if (string.IsNullOrEmpty(file))
        {
            return false;
        }

        if (!AllowRepetitive && ExistPredicate != null)
        {
            return !ExistPredicate(file);
        }

        return true;
    }


    public static bool FileExists(IReadOnlyList<FileViewModel> list, string path) =>
        list.Any(f => PathEqualityComparer.Instance.Equals(f.FileName, path));


    [RelayCommand]
    private async Task SelectFile()
    {
        if (MultipleSelect)
        {
            IReadOnlyList<string> fileList = await App.GetService<IFilePikerService>()
                .PickMultipleFilesAsync(Filter);

            if (fileList.Count > 0 && IsFileValid(fileList[0]))
            {
                FileName = fileList[0];
            }

            if (fileList.Count > 1)
            {
                UpdateMultipleFileOverride(fileList.ToArray()[1..]);
            }

            return;
        }

        string? fileName = await App.GetService<IFilePikerService>()
            .PickSingleFileAsync(Filter);

        if (IsFileValid(fileName))
        {
            FileName = fileName;
        }
    }


    [RelayCommand]
    private void Remove() => RemoveCallback?.Invoke(this);
}

public class PathEqualityComparer : IEqualityComparer<string>
{
    public static PathEqualityComparer Instance => new();


    public bool Equals(string? x, string? y)
    {
        if (ReferenceEquals(x, y))
        {
            return true;
        }

        if (x == null || y == null)
        {
            return false;
        }

        return string.Equals(Path.GetFullPath(x), Path.GetFullPath(y), StringComparison.OrdinalIgnoreCase);
    }

    public int GetHashCode(string obj) => HashCode.Combine(obj);
}